<?php
declare (strict_types=1);

namespace app\admin\service\promotion;

use app\admin\logic\promotion\Promotion as PromotionLogic;
use app\admin\logic\promotion\PromotionBargainData;
use app\admin\logic\promotion\PromotionTuan;
use app\admin\logic\promotion\PromotionTuanData;
use app\common\exception\NotFoundException;
use app\common\service\BaseService;
use eduline\admin\libs\pageform\FormItem;
use eduline\admin\libs\pagelist\ListItem;
use eduline\admin\page\PageForm;
use eduline\admin\page\PageList;
use think\annotation\Inject;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Request;
use think\Response;

/**
 * Class Promotion
 *
 * @package app\admin\service\promotion
 */
class Promotion
{
    /**
     * @Inject()
     *
     * @var PromotionLogic
     */
    protected $promotionLogic;
    /**
     * @Inject()
     *
     * @var PromotionBargainData
     */
    protected $promotionBargainDataLogic;

    /**
     * @Inject()
     *
     * @var PromotionTuan
     */
    protected $promotionTuanLogic;

    /**
     * @Inject()
     *
     * @var PromotionTuanData
     */
    protected $promotionTuanDataLogic;

    /**
     * 活动列表
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/4/14
     *
     * @param string $type
     * @return Response
     * @throws DbException
     */
    public function index(string $type)
    {
        $typeList = ['discount' => 1, 'seckill' => 2, 'bargain' => 3, 'tuan' => 4];
        if (!isset($typeList[$type])) {
            throw new NotFoundException();
        }
        $type = $typeList[$type];
        $map  = [];
        // 课程类型
        if (Request::has('product_type', 'get', true)) {
            $map[] = ['product_type_id', '=', Request::get('product_type/d')];
        }
        //状态
        if (Request::has('status', 'get', true) && Request::get('status/d', -1) !== -1) {
            $map[] = ['status', '=', Request::get('status/d')];
        }

        $data = $this->promotionLogic->getList($type, $map);
        // 定义字段
        $keyList = [
            'title'             => ListItem::make('custom')->title('课程名称'),
            'product_type_text' => ListItem::make()->title('课程类型'),
            'pronmotion_time'   => ListItem::make('custom')->title('活动时间'),
            'price'             => ListItem::make('custom')->title('价格'),
            'discount'          => ListItem::make()->title('折扣')->visible($type == 1),
            'num'               => ListItem::make()->title('所需人数')->visible($type == 3 || $type == 4),
            'status'            => ListItem::make('custom')->title('启用状态'),
            'active_status'     => ListItem::make('custom')->title('活动状态'),
            'update_time'       => ListItem::make()->title('更新时间')
        ];
        // 课程类型
        $productType = $this->promotionLogic->getProductTypeOptions();
        // 状态
        $status = $this->promotionLogic->getStatusOptions();
        // 搜索字段
        $searchKey = [
            'product_type' => FormItem::make('select')->title(false)->placeholder('课程类型')->options($productType),
            'status'       => FormItem::make('select')->title(false)->placeholder('启用状态')->options($status),
        ];

        // 设置表单
        $list = new PageList();
        // 表单字段
        $list->pageKey   = $keyList;
        $list->datas     = $data;
        $list->searchKey = $searchKey;

        return $list->send();
    }

    /**
     * 新建活动
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/4/14
     *
     * @param string $type
     * @return Response
     * @throws DbException
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     */
    public function create(string $type)
    {
        if (Request::isPost()) {
            $data = Request::post();
            $this->promotionLogic->createPromotion($type, $data);

            return BaseService::parseToData([], 1, '新建成功');
        }
        /* 创建课程界面配置 */
        $keyList = $this->keyListInit($type);
        // 设置表单
        $form = new PageForm();
        // 表单字段
        $form->pageKey     = $keyList;
        $form->saveMethod  = 'POST';
        $form->savePostUrl = '/admin/promotion/' . $type . '/create';

        return $form->send();
    }

    /**
     * 编辑
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/4/15
     *
     * @param string $type
     * @param int    $id
     * @return Response
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function edit(string $type, int $id)
    {
        if (Request::isPut()) {
            $data = Request::post();
            $this->promotionLogic->editPromotion($type, $id, $data);

            return BaseService::parseToData([], 1, '更新成功');
        }
        $datas         = $this->promotionLogic->getPromotionById($id);
        $datas->course = $datas->getAttr('product_id');
        $datas->time   = [$datas->start_time, $datas->end_time];
        /* 创建课程界面配置 */
        $keyList = $this->keyListInit($type);
        // 设置表单
        $form = new PageForm();
        // 表单字段
        $form->pageKey     = $keyList;
        $form->datas       = $datas;
        $form->saveMethod  = 'PUT';
        $form->savePostUrl = '/admin/promotion/' . $type . '/' . $id . '/edit';

        return $form->send();
    }

    /**
     * 新增/编辑列表字段
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/4/14
     *
     * @param string $type
     * @param bool   $isCreate
     * @return array
     */
    public function keyListInit(string $type, bool $isCreate = true)
    {
        // 定义字段
        $keyList = [
            'course' => FormItem::make('custom')->title('课程')->required(),
            'time'   => FormItem::make('date')->title('活动时间')->dateType(FormItem::option('DateType', 'DATETIME_RANGE'))->format('yyyy-MM-dd HH:mm')->required(),
        ];
        $type    = $this->promotionLogic->getPromotionType($type);
        switch ($type) {
            case 1:// 限时打折
                $keyList['discount'] = FormItem::make('inputNumber')->title('折扣')->min(0.1)->max(9.9)->step(0.1)->precision(2)->help('最低9.9折，最高0.1折')->required();
                break;
            case 2:// 秒杀
                $keyList['price'] = FormItem::make('inputNumber')->title('秒杀价')->min(0.01)->precision(2)->required();
                break;
            case 3:// 砍价
                $keyList['price'] = FormItem::make('inputNumber')->title('砍价成功价')->min(0.01)->precision(2)->required()->help('可砍价的最低金额');
                $keyList['num']   = FormItem::make('inputNumber')->title('砍价所需人数')->required();
                break;
            case 4:// 拼团
                $keyList['price']  = FormItem::make('inputNumber')->title('拼团价')->min(0.01)->precision(2)->required();
                $keyList['num']    = FormItem::make('inputNumber')->title('拼团所需人数')->required();
                $keyList['expiry'] = FormItem::make('inputNumber')->title('拼团有效期')->precision(1)->min(0.1)->step(0.1)->help('1. 开团后多长时间内需完成拼团<br />2. 单位: 小时')->required();
                break;
        }

        return $keyList;
    }

    /**
     * 编辑单个字段信息
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/3/10
     *
     * @param int    $id
     * @param string $field
     * @return Response
     */
    public function editField(int $id, string $field)
    {
        $value  = Request::put($field);
        $module = $this->promotionLogic->editField($id, $field, $value);

        return BaseService::parseToData($module, 1, '更新成功');
    }

    /**
     * 单个删除
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2020/12/21
     *
     * @param int $id
     * @return Response
     */
    public function delete(int $id)
    {
        $this->promotionLogic->deletePromotion($id);

        return BaseService::parseToData([], 1, '删除成功');
    }

    /**
     * 活动报表
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/4/21
     *
     * @param int    $id
     * @param string $type
     * @return Response
     * @throws DbException
     */
    public function report(int $id, string $type)
    {
        switch ($type) {
            // TODO::
            case 'bargain':// 砍价
                $list = $this->bargainReport($id);
                break;
            // TODO::
            case 'tuan':// 拼团
                $list = $this->tuanReport($id);
                break;
            default:// 折扣、秒杀
                $list = $this->orderReport($id);
                break;
        }

        return $list->send();
    }

    /**
     * 通用的订单报表
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/4/22
     *
     * @param $id
     * @return PageList
     * @throws DbException
     */
    private function orderReport($id): PageList
    {
        $map = [];
        if (Request::has('status', 'get', true)) {
            $status = Request::get('status/d') == 1 ? '20' : '10,30,40,50,60,70';
            $map[]  = ['pdorder.status', 'in', $status];
        }

        if (Request::has('time', 'get', true)) {
            $time  = Request::get('time/a');
            $stime = strtotime(date('Y-m-d 00:00:00', strtotime($time[0])));
            $etime = strtotime(date('Y-m-d 00:00:00', strtotime($time[1]))) + 86399;
            $map[] = ['__TABLE__.create_time', 'between', [$stime, $etime]];
        }

        $data = $this->promotionLogic->getPromotionOrder($id, $map)->bindAttr('user', ['phone', 'user_name'])
            ->bindAttr('transaction', ['payment_type_text', 'payment_time'])
            ->hidden(['user', 'transaction', 'pdorder']);
        // 定义字段
        $keyList = [
            'order_sub_no'      => ListItem::make()->title('订单号'),
            'price'             => ListItem::make('custom')->title('价格'),
            'discount'          => ListItem::make('custom')->title('优惠'),
            'phone'             => ListItem::make()->title('购买者'),
            'create_time'       => ListItem::make()->title('下单时间'),
            'payment_time'      => ListItem::make()->title('支付时间'),
            'payment_type_text' => ListItem::make()->title('支付方式'),
            'from'              => ListItem::make()->title('订单来源'),
            'status_text'       => ListItem::make()->title('订单状态'),
        ];
        // 状态
        $statusOptions = [
            ['title' => '成功购买', 'value' => 1],
            ['title' => '未成功购买', 'value' => 2],
        ];

        // 搜索字段
        $searchKey = [
            'status' => FormItem::make('select')->title(false)->placeholder('购买状态')->options($statusOptions),
            'time'   => FormItem::make('date')->title(false)->dateType(FormItem::option('DateType', 'DATE_RANGE'))->startPlaceholder('下单开始时间')->endPlaceholder('下单截止时间')->format('yyyy-MM-dd'),
        ];

        // 设置表单
        $list = new PageList();
        // 表单字段
        $list->pageKey   = $keyList;
        $list->datas     = $data;
        $list->searchKey = $searchKey;

        return $list;
    }

    /**
     * 砍价报表
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/4/23
     *
     * @param int $id
     * @return PageList
     * @throws DbException
     */
    private function bargainReport(int $id)
    {
        $map = [];
        if (Request::has('status', 'get', true)) {
            $status = Request::get('status/d');
            switch ($status) {
                case 1: // 进行中
                    $map[] = ['done', '=', 0];
                    break;
                case 2:// 砍价失败
                    break;
                case 3:// 砍价成功
                    $map[] = ['done', '=', 1];
                    break;
            }
        }

        if (Request::has('time', 'get', true)) {
            $time  = Request::get('time/a');
            $stime = strtotime(date('Y-m-d 00:00:00', strtotime($time[0])));
            $etime = strtotime(date('Y-m-d 00:00:00', strtotime($time[1]))) + 86399;
            $map[] = ['__TABLE__.create_time', 'between', [$stime, $etime]];
        }

        $data = $this->promotionLogic->getPromotionBargain($id, $map)->bindAttr('user', ['phone', 'user_name'])
            ->hidden(['user']);
        // 定义字段
        $keyList = [
            'phone'        => ListItem::make()->title('砍价发起用户'),
            'number'       => ListItem::make('custom')->title('已砍价人数/需砍价人数'),
            'remain_nums'  => ListItem::make()->title('还须砍价人数'),
            'price'        => ListItem::make('custom')->title('已砍价金额/需砍价金额'),
            'remain_price' => ListItem::make('custom')->title('还须砍价金额'),
            'create_time'  => ListItem::make()->title('砍价发起时间'),
            'status'       => ListItem::make('custom')->title('砍价状态')
        ];
        // 状态
        $statusOptions = [
            ['title' => '进行中', 'value' => 1],
            // ['title' => '砍价失败', 'value' => 2],
            ['title' => '砍价成功', 'value' => 3]
        ];

        // 搜索字段
        $searchKey = [
            'status' => FormItem::make('select')->title(false)->placeholder('砍价状态')->options($statusOptions),
            'time'   => FormItem::make('date')->title(false)->dateType(FormItem::option('DateType', 'DATE_RANGE'))->startPlaceholder('发起开始时间')->endPlaceholder('发起截止时间')->format('yyyy-MM-dd'),
        ];

        // 设置表单
        $list = new PageList();
        // 表单字段
        $list->pageKey   = $keyList;
        $list->datas     = $data;
        $list->searchKey = $searchKey;

        return $list;
    }

    /**
     * 获取砍价记录
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/4/22
     *
     * @param int $bargainId
     * @return Response
     * @throws DbException
     */
    public function reportBargainInfo(int $bargainId)
    {
        $datas       = $this->promotionBargainDataLogic->getBargainListById($bargainId)->bindAttr('user', ['phone', 'user_name'])
            ->hidden(['user']);
        $list        = new PageList();
        $list->datas = $datas;

        return $list->send();
    }

    /**
     * 拼团报表
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/4/24
     *
     * @param int $id
     * @return PageList
     * @throws DbException
     */
    private function tuanReport(int $id)
    {
        $map = [];
        if (Request::has('status', 'get', true)) {
            $status = Request::get('status/d');
            // TODO::按时间计算开团成功与失败
            $map[] = ['__TABLE__.status', '=', $status];
        }

        if (Request::has('time', 'get', true)) {
            $time  = Request::get('time/a');
            $stime = strtotime(date('Y-m-d 00:00:00', strtotime($time[0])));
            $etime = strtotime(date('Y-m-d 00:00:00', strtotime($time[1]))) + 86399;
            $map[] = ['__TABLE__.create_time', 'between', [$stime, $etime]];
        }

        $data = $this->promotionLogic->getPromotionTuan($id, $map)->bindAttr('user', ['phone', 'user_name'])
            ->hidden(['user'])->append(['remain_nums']);
        // 定义字段
        $keyList = [
            'phone'       => ListItem::make()->title('拼团发起用户'),
            'number'      => ListItem::make('custom')->title('已加入人数/所需总人数'),
            'remain_nums' => ListItem::make()->title('还须拼团人数'),
            'create_time' => ListItem::make()->title('开团时间'),
            'expiry_time' => ListItem::make()->title('拼团有效期截止'),
            'status'      => ListItem::make('custom')->title('拼团状态')
        ];
        // 状态
        $statusOptions = [
            ['title' => '待支付开团', 'value' => 0],
            ['title' => '开团成功', 'value' => 1],
            ['title' => '拼团成功', 'value' => 2],
            ['title' => '拼团失败', 'value' => 3]
        ];

        // 搜索字段
        $searchKey = [
            'status' => FormItem::make('select')->title(false)->placeholder('拼团状态')->options($statusOptions),
            'time'   => FormItem::make('date')->title(false)->dateType(FormItem::option('DateType', 'DATE_RANGE'))->startPlaceholder('开团开始时间')->endPlaceholder('开团截止时间')->format('yyyy-MM-dd'),
        ];

        // 设置表单
        $list = new PageList();
        // 表单字段
        $list->pageKey   = $keyList;
        $list->datas     = $data;
        $list->searchKey = $searchKey;

        return $list;
    }

    /**
     * 获取团的数据
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/4/24
     *
     * @param int $id
     * @param int $tuanId
     * @return Response
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function reportTuanInfo(int $id, int $tuanId)
    {
        $datas = [];
        $type  = Request::get('type/d', 1);
        if ($type == 1) {
            $tuanInfo = $this->promotionTuanLogic->getTuanInfoById($id)->bindAttr('user', ['phone', 'user_name'])->append(['remain_nums'])
                ->hidden(['user']);

            $tuanDatas           = $this->promotionTuanDataLogic->getTuanDatas($tuanId, '1,2');
            $datas['tuan_info']  = $tuanInfo;
            $datas['tuan_datas'] = $tuanDatas;
        } else {
            $datas['tuan_datas'] = $this->promotionTuanDataLogic->getTuanDatas($tuanId, '0');
        }

        return BaseService::parseToData($datas, 1);
    }

}
